package com.littleindian.radioskypipeviewer;

import java.nio.ByteBuffer;
import java.util.ArrayList;

import android.graphics.Point;
import android.util.Log;


public class RSPStreamProcessor {
	private static String TAG = Viewer.TAG;
	private static String TAG1 = "BufferProcessor: ";
	
	private enum State {
		procInit,
		procFF,
		procPound,
		proc0,
		procTime,
		procTilde,
		procSpace2,
		procY,	
	};
	
	
	private State mState = State.procInit;
	private String mTime;
	private int mLoadPos;
	private byte[] mca;
	private ByteBuffer mBuffer;
	
	public RSPStreamProcessor(int bufferSize) {
		mca = new byte[bufferSize];
		mBuffer = ByteBuffer.wrap(mca);
		mLoadPos = 0;
	}
	
	
	private int findChar(ByteBuffer buf, int c) {
		return findChar(buf, c, 0);
	}
	
	private int findChar(ByteBuffer buf, int c, int start) {
		int result = -1;
		for(int i=start; i<buf.capacity(); ++i) {
			if((int)buf.get(i) == c) {
				result = i;
				break;
			}
		}
		return result;
	}
	
	private void dumpBuffer(int startPos, int midPos, int endPos, int loadPos){
		String log = new String();

		for(int i=0;i<mBuffer.capacity();++i) {
			if(i<10)
				log += "[0"+i+"]";
			else
				log += "["+i+"]";
			
		}
		Log.w(TAG,log);

		log="";
		for(int i=0;i<mBuffer.capacity();++i) {
			log += " "+(char)mBuffer.get(i)+"  ";
		}
		Log.w(TAG,log);

		log="";
		for(int i=0;i<mBuffer.capacity();++i) {
			if(i==startPos)
				log += " s  ";
			else if(i==midPos)
				log += " m  ";
			else if(i==endPos)
				log += " e  ";
			else if(i==loadPos)
				log += " L ";
			else
				log += "    ";
		}
		Log.w(TAG,log);
		Log.w(TAG,"s="+startPos +" m="+midPos +" e="+endPos +" L="+loadPos);
		
	}
	

	byte[] yBytes = new byte[64];
	int yLoadPos = 0;
	byte[] xBytes = new byte[64];
	int xLoadPos = 0;
	String strX, strY;
	
    public ArrayList<Point> processBuffer(byte[] ba, int nBytes) {
		ArrayList<Point> resultPts = new ArrayList<Point>();

		// FF # 0 <space> <time> ~ <space> <temperature>
    	byte b;
    	//String chars = new String(ba);
    	//Log.e("REMOVE", chars);
    	nBytes = Math.min(nBytes,ba.length);
    	for(int i=0; i<nBytes; ++i) {
    		b = ba[i];
    		
    		// Log.d(TAG, "state="+mState +" b=" + (char)b);
    		switch(mState) {
        	
        	case procInit:
        		if(b==-1) {
        			mState = State.procFF;
        			//Log.d(TAG, TAG1+"STATE_CHANGE to " + mState);
        		}
        	break;
    		
        	case procFF:      
        		if(b == '#') {
        			mState = State.procPound;
        			//Log.d(TAG, TAG1+"STATE_CHANGE to " + mState);
        		} else {
        			mState = State.procInit;
        		}
        	break;
        	
        	case procPound:
        		if(b == '0') {
        			mState = State.proc0;
        			//Log.d(TAG, TAG1+"STATE_CHANGE to " + mState);
        		} else {
        			mState = State.procInit;
        		}
        	break;

        	case proc0:       
        		if(b==' ') {
        			mState = State.procTime;
        			xLoadPos = 0;
        			//Log.d(TAG, TAG1+"STATE_CHANGE to " + mState);
        		}
        		else {
        			mState = State.procInit;
        		}
        	case procTime:
        		if(b == '~') {
        			mState = State.procY;
        			yLoadPos = 0;
        			//Log.d(TAG, TAG1+"STATE_CHANGE to " + mState);
	    		} else if (b == '#') {
	    			mState = State.procInit;
	    		} else {
        			if( xLoadPos < xBytes.length )
        				xBytes[xLoadPos++] = b;
        		}
        		break; 
        	
        	case procY:
        		if(b == -1 ) {
					try {
	        			strX = new String(xBytes);
						strX = strX.substring(0, xLoadPos-1).trim();

						strY = new String(yBytes);
						strY = strY.substring(0, yLoadPos-1).trim();

						//Log.d(TAG, TAG1+"strX="+strX +" strY="+strY);

						Float X = Float.parseFloat(strX);
						Float Y = Float.parseFloat(strY);
						
						Log.d(TAG, TAG1+"DATA=<"+X+","+Y+">");
						
						Point p = new Point((int)(X.floatValue()*1000000), (int)(Y.floatValue()*1000));
						resultPts.add(p);
					} catch (NumberFormatException e) {
						Log.d(TAG,"Invalid data: "+ new String(ba));
						Log.d(TAG,"strX,strY: ["+strX +"] [" + strY + "]");
						Log.d(TAG,"state="+mState + "xpos="+xLoadPos +" ypos="+yLoadPos);
						Log.e(TAG, e.toString(),e );
					}        			
        			
        			
        			mState = State.procInit;
        			//Log.d(TAG, TAG1+"STATE_CHANGE to " + mState);
        			
        		} else {
        			if( yLoadPos < yBytes.length )
        				yBytes[yLoadPos++] = b;
        		}
        			
        		break;
        	}
    		
        	if( b == -1 ) {
    			xLoadPos = 0;
    			yLoadPos = 0;
        		mState = State.procFF;
        	}

    	} // for(..)
    	return resultPts;
    }

	
	
	// TODO: size this with the process buffer
	byte valb[] = new byte[128];

	public ArrayList<Point> processBufferOld2(byte[] ba) {
		ArrayList<Point> resultPts = new ArrayList<Point>();
		
		try {

			// [-17][-65][-67][]...[][
			// Validate the buffer can hold incoming data.
			int numToAdd = mBuffer.capacity() - mLoadPos;
			numToAdd = Math.min(numToAdd, ba.length);
			
			Log.d(TAG,"adding " + numToAdd + " bytes at mLoadPos=" + mLoadPos);
						
			// Append the buffer with incoming data
			mBuffer.position(mLoadPos);
			mBuffer.put(ba,  0, numToAdd);
			mLoadPos += numToAdd;


			int startPos = 0, midPos = -1,endPos = -1;
			int lastGoodEndPos = -1;
			
			while( startPos < mLoadPos ) {
				endPos = -1;
				midPos = -1;

				startPos = findChar(mBuffer, '#', startPos);
				if(startPos < 0)
					break;

				endPos = findChar(mBuffer, -1, startPos + 3);
				//Log.d(TAG, TAG1+" <<< endPos="+endPos);
				if(endPos < 0)
					break;
		
				//midPos = strBuffer.indexOf('~', startPos + 3 );
				midPos = findChar(mBuffer, '~', startPos + 3);
				//Log.d(TAG, TAG1+" <<< midPos="+midPos);
				if(midPos < 0)
					break;
				
				//dumpBuffer(startPos, midPos, endPos, mLoadPos);
				if(startPos < midPos  && midPos < endPos) {
				
					int n;
					
					n = 0;
					for(int i=startPos+3; i<midPos-1; ++i, ++n)
						valb[n] = mBuffer.get(i);
					for(int i=n; i<valb.length; ++i)
						valb[i] = 0;
					String strX = new String(valb);
					strX = strX.substring(0,n-1);
					
					n = 0;
					for(int i=midPos+1; i<endPos-1; ++i, ++n)
						valb[n] = mBuffer.get(i);
					for(int i=n; i<valb.length; ++i)
						valb[i] = 0;
					String strY = new String(valb);
					strY = strY.substring(0,n-1);
	
					//Log.d(TAG, TAG1+"strX="+strX +" strY="+strY);
					try {
						Float X = Float.parseFloat(strX);
						Float Y = Float.parseFloat(strY);
						Log.d(TAG, TAG1+"< x="+X +", y="+Y + ">");
						
						Point p = new Point((int)(X.floatValue()*1000), (int)(Y.floatValue()*1000));
						resultPts.add(p);
					} catch (NumberFormatException e) {
						
					}
					
					lastGoodEndPos = endPos;
	
				}
				startPos = endPos + 1;
			} // while(startPos < mLoadPos)
			
			
			// Handle trailing characters
			if( lastGoodEndPos > -1 ){
				int n = 0;
				for(int i=lastGoodEndPos+1; i < mLoadPos; ++i)
					mBuffer.put(n++, mBuffer.get(i));
				for(int i=mLoadPos; i < mBuffer.capacity(); ++i)
					mBuffer.put(i, (byte)0);
				mLoadPos = n;
				mBuffer.clear();
			} else if(mLoadPos >= mBuffer.capacity()) {
				// Bad buffer contents.
				// - reset buffer
				for(int i=0; i < mBuffer.capacity(); ++i)
					mBuffer.put(i, (byte)0);
				mLoadPos = 0;
				mBuffer.clear();
				
			}
			
			Log.d(TAG,"returning "+resultPts.size()+" points. mLoadPos="+mLoadPos);
			if(resultPts.size() == 0)
				dumpBuffer(startPos, midPos, endPos, mLoadPos);
		} catch (Exception e) {
			Log.e(TAG, TAG1+"Exception: " + e.toString() + "\nmLoadPos="+mLoadPos, e);
		}
		return resultPts;
	}
	
	

}
